package com.sky.service.impl;


import com.ejlchina.searcher.BeanSearcher;
import com.ejlchina.searcher.operator.Between;
import com.ejlchina.searcher.operator.Equal;
import com.ejlchina.searcher.operator.LessEqual;
import com.ejlchina.searcher.operator.LessThan;
import com.ejlchina.searcher.util.MapUtils;
import com.sky.constant.OrderConstant;
import com.sky.dto.TurnoverReportDto;
import com.sky.entity.Orders;
import com.sky.entity.User;
import com.sky.exception.ServiceException;
import com.sky.service.ReportService;
import com.sky.service.WorkspaceService;
import com.sky.utils.DateUtils;
import com.sky.vo.SalesTop10ReportVO;
import lombok.extern.slf4j.Slf4j;
import org.apache.poi.xssf.usermodel.XSSFCell;
import org.apache.poi.xssf.usermodel.XSSFRow;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.InputStream;
import java.text.SimpleDateFormat;
import java.time.*;
import java.time.format.DateTimeFormatter;
import java.time.temporal.ChronoUnit;
import java.util.*;
import java.util.stream.Collectors;

@Service
@Slf4j
public class ReportServiceImpl implements ReportService {

    @Autowired
    private BeanSearcher beanSearcher;

    @Autowired
    private WorkspaceService workspaceService;


    /**
     * 营业额统计
     * @param  dto 统计参数
     * @return
     */
    @Override
    public Map<String,Object> getTurnoverStatistics(TurnoverReportDto dto) {
        HashMap<String, Object> result = new HashMap<>();

        List<String> dateList = getDateList(dto);
        List<Double> turnoverList = new ArrayList<>();

        if (!CollectionUtils.isEmpty(dateList)){
            dateList.forEach(item ->{
                String begin = item + " 00:00:00";
                String end = item + " 23:59:59";

                SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
                Date beginTime;
                Date endTime;
                try {
                    beginTime = sdf.parse(begin);
                    endTime = sdf.parse(end);
                } catch (Exception e) {
                   throw new ServiceException(e.getMessage());
                }

                Map<String, Object> build = MapUtils.builder()
                        .field(Orders::getStatus, OrderConstant.COMPLETED).op(Equal.class)
                        .field(Orders::getOrderTime,beginTime,endTime).op(Between.class)
                        .build();
                double amount = beanSearcher.searchSum(Orders.class, build, "amount").doubleValue();
                turnoverList.add(amount);
            });
        }

        result.put("dateList", dateList);
        result.put("turnoverList", turnoverList);
        return result;
    }

    /**
     * 用户数量统计
     * @param  dto 统计参数
     * @return
     */
    @Override
    public Map<String, Object> getUserStatistics(TurnoverReportDto dto) {
        HashMap<String, Object> result = new HashMap<>();

        List<String> dateList = getDateList(dto);
        List<Integer> totalUserList = new ArrayList<>();
        List<Integer> newUserList = new ArrayList<>();

        if (!CollectionUtils.isEmpty(dateList)){
            dateList.forEach(item ->{
                String begin = item + " 00:00:00";
                String end = item + " 23:59:59";

                SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
                Date beginTime;
                Date endTime;
                try {
                    beginTime = sdf.parse(begin);
                    endTime = sdf.parse(end);
                } catch (Exception e) {
                    throw new ServiceException(e.getMessage());
                }

                //统计每天新增的用户数量
                Map<String, Object> build = MapUtils.builder()
                        .field(User::getCreateTime,beginTime,endTime).op(Between.class)
                        .build();
                int newUserCount = beanSearcher.searchCount(User.class, build).intValue();
                newUserList.add(newUserCount);

                //统计所有的用户数量
                Map<String, Object> build1 = MapUtils.builder()
                        .field(User::getCreateTime,endTime).op(LessEqual.class)
                        .build();
                int totalUserCount = beanSearcher.searchCount(User.class, build1).intValue();
                totalUserList.add(totalUserCount);
            });
        }

        result.put("dateList", dateList);
        result.put("totalUserList", totalUserList);
        result.put("newUserList", newUserList);
        return result;
    }

    @Override
    public Map<String, Object> getOrdersStatistics(TurnoverReportDto dto) {
        HashMap<String, Object> result = new HashMap<>();

        List<String> dateList = getDateList(dto);
        List<Integer> orderCountList = new ArrayList<>();  //每天的订单总数集合
        List<Integer> validOrderCountList = new ArrayList<>(); //每日有效订单数集合

        int totalOrderCount = 0; //订单总数
        Integer validOrderCount = 0; //有效订单总数
        double orderCompletionRate = 0.0; //订单完成率

        if (!CollectionUtils.isEmpty(dateList)) {
            dateList.forEach(item -> {
                String begin = item + " 00:00:00";
                String end = item + " 23:59:59";

                SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
                Date beginTime;
                Date endTime;
                try {
                    beginTime = sdf.parse(begin);
                    endTime = sdf.parse(end);
                } catch (Exception e) {
                    throw new ServiceException(e.getMessage());
                }

                //统计每天的订单总数
                Map<String, Object> build = MapUtils.builder()
                        .field(Orders::getOrderTime, beginTime, endTime).op(Between.class)
                        .build();
                int orderCount = beanSearcher.searchCount(Orders.class, build).intValue();
                orderCountList.add(orderCount);

                //统计每日有效订单数
                Map<String, Object> build1 = MapUtils.builder()
                        .field(Orders::getStatus, OrderConstant.COMPLETED).op(Equal.class)
                        .field(Orders::getOrderTime, beginTime, endTime).op(Between.class)
                        .build();
                int validOrderCountDay = beanSearcher.searchCount(Orders.class, build1).intValue();
                validOrderCountList.add(validOrderCountDay);
            });

            //计算订单总数
            totalOrderCount = orderCountList.stream().reduce(Integer::sum).get();
            //计算有效订单总数
            validOrderCount = validOrderCountList.stream().reduce(Integer::sum).get();
            //计算订单完成率
            if (totalOrderCount != 0){
                orderCompletionRate = validOrderCount.doubleValue() / totalOrderCount;
            }

        }

        result.put("dateList", dateList); //日期
        result.put("orderCountList", orderCountList);  //每日订单数
        result.put("validOrderCountList", validOrderCountList); //每日有效订单数
        result.put("totalOrderCount", totalOrderCount);  //订单总数
        result.put("validOrderCount", validOrderCount);  //有效订单数
        result.put("orderCompletionRate", orderCompletionRate);  //订单完成率
        return result;
    }


    /**
     * 统计销量前10的商品
     * @param  dto 统计参数
     * @return
     */
    @Override
    public Map<String, Object> getTop10(TurnoverReportDto dto) {
        HashMap<String, Object> result = new HashMap<>();

        Date beginTime = dto.getBeginTime();
        Date endTime = dto.getEndTime();

        SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
        String begin = dateFormat.format(beginTime);
        String end = dateFormat.format(endTime);

        begin = begin + " 00:00:00";
        end = end + " 23:59:59";

        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        try {
            beginTime = sdf.parse(begin);
            endTime = sdf.parse(end);
        } catch (Exception e) {
            throw new ServiceException(e.getMessage());
        }

        List<String> nameList = new ArrayList<>();
        List<Integer> numberList = new ArrayList<>();

        //统计每天新增的用户数量
        Map<String, Object> build = MapUtils.builder()
                .page(1,10)
                .put("whereAnd"," o.order_time BETWEEN '"+begin +"' and '" + end + "' and o.status = "+ OrderConstant.COMPLETED)
                .build();
        List<SalesTop10ReportVO> salesTop10ReportVOS = beanSearcher.searchAll(SalesTop10ReportVO.class, build);
        if (!CollectionUtils.isEmpty(salesTop10ReportVOS)){
            List<String> names = salesTop10ReportVOS.stream().map(SalesTop10ReportVO::getName).toList();
            nameList.addAll(names);
            List<Integer> sumNumbers = salesTop10ReportVOS.stream().map(SalesTop10ReportVO::getSumNumber).toList();
            numberList.addAll(sumNumbers);
        }

        result.put("nameList", nameList); //商品名称列表
        result.put("numberList", numberList);  //销量列表
        return result;
    }

    /**
     * 导出30天运营文件Excel
     * @param  response 返回流
     * @return
     */
    @Override
    public void exportBusinessData(HttpServletResponse response) {
        //查询概览数据
        Date beginTime = DateUtils.minusDay(-30);
        Date endTime = DateUtils.minusDay(-1);
        String begin = DateUtils.parseDateToStr(beginTime,"yyyy-MM-dd") + " 00:00:00";
        String end = DateUtils.parseDateToStr(endTime,"yyyy-MM-dd") + " 23:59:59";
        Map<String, Object> businessData = workspaceService.getBusinessData(begin,end);

        //通过POI写入excel
        InputStream resourceAsStream = this.getClass().getClassLoader().getResourceAsStream("template/运营数据报表模板.xlsx");
        try {
            XSSFWorkbook workbook = new XSSFWorkbook(Objects.requireNonNull(resourceAsStream));
            //填充数据
            XSSFSheet sheet = workbook.getSheet("sheet1");
            //填充时间
            sheet.getRow(1).getCell(1).setCellValue("时间：" + begin +"至" + end);
            //填充概览数据
            Double turnover = (Double) businessData.get("turnover"); //营业额
            Integer validOrderCount = (Integer) businessData.get("validOrderCount"); //有效订单数
            Double orderCompletionRate = (Double) businessData.get("orderCompletionRate"); //订单完成率
            Double unitPrice = (Double) businessData.get("unitPrice"); //平均客单价
            Integer newUsers = (Integer) businessData.get("newUsers"); //新增用户数
            sheet.getRow(3).getCell(2).setCellValue(turnover);
            sheet.getRow(4).getCell(2).setCellValue(validOrderCount);
            sheet.getRow(3).getCell(4).setCellValue(orderCompletionRate);
            sheet.getRow(4).getCell(4).setCellValue(unitPrice);
            sheet.getRow(3).getCell(6).setCellValue(newUsers);

            //获取明细数据
            TurnoverReportDto turnoverReportDto = new TurnoverReportDto();
            turnoverReportDto.setBeginTime(beginTime);
            turnoverReportDto.setEndTime(endTime);
            List<String> dateList = this.getDateList(turnoverReportDto);
            if (!CollectionUtils.isEmpty(dateList)){
                for (int i = 0; i < dateList.size(); i++) {
                    //查询某一天的明细
                    String beginDate = dateList.get(i) + " 00:00:00";
                    String endDate = dateList.get(i) + " 23:59:59";
                    Map<String, Object> data = workspaceService.getBusinessData(beginDate, endDate);
                    Double turnoverByDay = (Double) data.get("turnover"); //营业额
                    Integer validOrderCountByDay = (Integer) data.get("validOrderCount"); //有效订单数
                    Double orderCompletionRateByDay = (Double) data.get("orderCompletionRate"); //订单完成率
                    Double unitPriceByDay = (Double) data.get("unitPrice"); //平均客单价
                    Integer newUsersByDay = (Integer) data.get("newUsers"); //新增用户数

                    XSSFRow row = sheet.getRow(7 + i);
                    row.getCell(1).setCellValue(dateList.get(i));
                    row.getCell(2).setCellValue(turnoverByDay);
                    row.getCell(3).setCellValue(validOrderCountByDay);
                    row.getCell(4).setCellValue(orderCompletionRateByDay);
                    row.getCell(5).setCellValue(unitPriceByDay);
                    row.getCell(6).setCellValue(newUsersByDay);
                }
            }

            //3。获得输出流将Excel文件下载
            ServletOutputStream outputStream = response.getOutputStream();
            workbook.write(outputStream);

            //关闭资源
            outputStream.flush();
            outputStream.close();
            workbook.close();
        } catch (IOException e) {
            throw new ServiceException(e.getMessage());
        }
    }


    /**
     * @Author tzl
     * @Description 计算两个日期之间的所有日期
     * @Date 2023/8/6  17:37
     * @param dto 日期参数
     * @return List<String>
     **/
    private List<String> getDateList(TurnoverReportDto dto) {
        List<String> dateList = new ArrayList<>();

        // 起始日期
        LocalDate beginTime = dto.getBeginTime().toInstant().atZone(ZoneId.of("Asia/Shanghai")).toLocalDate();
        // 结束日期
        LocalDate endTime = dto.getEndTime().toInstant().atZone(ZoneId.of("Asia/Shanghai")).toLocalDate();

        // 计算日期之间的天数差距
        long daysBetween = ChronoUnit.DAYS.between(beginTime, endTime);

        // 循环遍历每一天的日期
        for (int i = 0; i <= daysBetween; i++) {
            LocalDate currentDate = beginTime.plusDays(i);
            // 将 LocalDate 转换为字符串
            String dateString = currentDate.format(DateTimeFormatter.ofPattern("yyyy-MM-dd"));
            dateList.add(dateString);
        }
        return dateList;
    }
}
